﻿using System;
using System.Collections.Generic;
using System.Linq;
using Missbot.Core.Base;
using Dolany.UtilityTool;
using JetBrains.Annotations;
using Missbot.AIModule.Base;

namespace Missbot.AIModule.SingleCommand.Dice
{
    [UsedImplicitly]
    public class DiceMod : IAIModule
    {
        public override string Name => "骰娘";
        public override AIPriority Priority => AIPriority.Low;

        private const int DiceCountMaxLimit = 200;
        private const int DiceSizeMaxLimit = 2000;

        [ModuleEnter(Command = ".rd", Description = "随机掷出一个100以内的数字")]
        public bool QuickDice(InboxSession session)
        {
            var rand = Rander.RandInt(100) + 1;
            session.SendBack($"你掷出了 {rand} 点！");
            return true;
        }

        protected override bool OnInboxImpl(InboxSession session)
        {
            if (base.OnInboxImpl(session))
            {
                return true;
            }

            var format = session.Text;
            if (string.IsNullOrEmpty(format))
            {
                return false;
            }

            var model = ParseDice(format);
            if (model == null || model.Count > DiceCountMaxLimit || model.Size > DiceSizeMaxLimit)
            {
                return false;
            }

            var result = ConsoleDice(model);
            SendResult(session, result);
            return true;
        }

        private DiceModel ParseDice(string msg)
        {
            var model = new DiceModel();

            if (msg.Contains("+"))
            {
                msg = CheckModify(msg, model);
            }

            return !msg.Contains("d") ? null : CheckD(msg, model);
        }

        private string CheckModify(string msg, DiceModel model)
        {
            if (msg.Count(p => p == '+') > 1)
            {
                return msg;
            }

            var strs1 = msg.Split(new[] { '+' }, StringSplitOptions.RemoveEmptyEntries);
            if (strs1.Length != 2)
            {
                return msg;
            }

            if (!int.TryParse(strs1[1], out var modify) || modify <= 0)
            {
                return msg;
            }

            model.Modify = modify;
            return strs1[0];
        }

        private DiceModel CheckD(string msg, DiceModel model)
        {
            if (msg.Count(p => p == 'd') > 1)
            {
                return null;
            }

            var strs = msg.Split(new[] { 'd' }, StringSplitOptions.RemoveEmptyEntries);
            if (strs.Length != 1 && strs.Length != 2)
            {
                return null;
            }

            if (strs.Length == 1)
            {
                if (!int.TryParse(strs[0], out var size) || size <= 0)
                {
                    return null;
                }

                model.Size = size;
                model.Count = 1;

                return model;
            }
            else
            {
                if (!int.TryParse(strs[0], out var count) ||
                    !int.TryParse(strs[1], out var size) ||
                    count <= 0 ||
                    size <= 0)
                {
                    return null;
                }

                model.Size = size;
                model.Count = count;

                return model;
            }
        }

        private DiceResultModel ConsoleDice(DiceModel model)
        {
            var result = new DiceResultModel
            {
                Modify = model.Modify,
                Result = new List<int>()
            };

            for (var i = 0; i < model.Count; i++)
            {
                var value = Rander.RandInt(model.Size) + 1;
                result.Result.Add(value);
            }

            return result;
        }

        private void SendResult(InboxSession session, DiceResultModel ResultModel)
        {
            var sum = ResultModel.Result.Sum(p => p);
            var sb = string.Join("+", ResultModel.Result.Select(p => p.ToString()));

            if (ResultModel.Modify != 0)
            {
                sum += ResultModel.Modify;
                sb += $"+{ResultModel.Modify}";
            }

            sb += $"={sum}";
            session.SendBack(sb);
        }
    }

    public class DiceModel
    {
        public int Count { get; set; }
        public int Size { get; set; }
        public int Modify { get; set; }
    }

    public class DiceResultModel
    {
        public List<int> Result { get; init; }
        public int Modify { get; init; }
    }
}